/**
 * 获取cookie
 * @param key cookie名称
 * @returns {string|null}
 */
function getCookie(key) {
    const reg = new RegExp(`(^| )${key}=([^;]*)(;|$)`);
    const arr = document.cookie.match(reg);
    if (arr) {
        return unescape(arr[2]);
    }
    return null;
}

/**
 * 设置cookie
 * @param name cookie名称
 * @param value cookie值
 * @param second 过期时间，默认1800
 * @param domain 域名，默认qq.com
 */
function setCookie(name, value, second = 1800, domain = 'qq.com') {
    const exp = new Date();
    exp.setTime(exp.getTime() + (second * 1000));
    document.cookie = `${name}=${encodeURIComponent(value)};domain=.${domain};path=/;expires=${exp.toGMTString()}`;
}

/**
 * 清除cookie
 * @param name cookie名称
 */
function clearCookie(name) {
    setCookie(name, '', -1);
}

/**
 * 获取url参数
 * @param name
 * @returns {string}
 */
function getUrlParameter(name) {
    const regex = new RegExp(`[\\?&]${name}=([^&#]*)`);
    const results = regex.exec(location.search);
    return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
}

/**
 * 更新url参数
 * @param url
 * @param parameterName
 * @param parameterValue
 * @param atStart
 * @returns {string}
 */
function updateParameter(url, parameterName, parameterValue, atStart /* Add param before others*/) {
    const replaceDuplicates = true;
    let urlhash; let cl;
    if (url.indexOf('#') > 0) {
        cl = url.indexOf('#');
        urlhash = url.substring(url.indexOf('#'), url.length);
    } else {
        urlhash = '';
        cl = url.length;
    }
    const sourceUrl = url.substring(0, cl);

    const urlParts = sourceUrl.split('?');
    let newQueryString = '';

    if (urlParts.length > 1) {
        const parameters = urlParts[1].split('&');
        for (let i = 0;
             (i < parameters.length); i++) {
            const parameterParts = parameters[i].split('=');
            if (!(replaceDuplicates && parameterParts[0] === parameterName)) {
                if (newQueryString === '') newQueryString = '?';
                else newQueryString += '&';
                newQueryString += `${parameterParts[0]}=${parameterParts[1] ? parameterParts[1] : ''}`;
            }
        }
    }
    if (newQueryString === '') newQueryString = '?';

    if (atStart) {
        newQueryString = `?${parameterName}=${parameterValue}${newQueryString.length > 1 ? `&${newQueryString.substring(1)}` : ''}`;
    } else {
        if (newQueryString !== '' && newQueryString !== '?') newQueryString += '&';
        newQueryString += `${parameterName}=${parameterValue ? parameterValue : ''}`;
    }
    return urlParts[0] + newQueryString + urlhash;
};

/**
 * filterXss
 * @param oriStr
 * @returns {*}
 */
function filterXSS(oriStr){
    if(!oriStr){
        return oriStr;
    }
    const charCodes=['3c','3e','27','22','28','29','60',{format:'script{}',chr:'3a'}];//要转义字符的16进制ASCII码[1<  2>  3'  4"  5(  6)  7`]
    let xssChars=[],filterChars=[],tmpFormat='{}',tmpChr;
    for(let i=0;i<charCodes.length;i++){
        if('string'==typeof charCodes[i]){
            tmpFormat='{}';
            tmpChr=charCodes[i];
        }else{
            tmpFormat=charCodes[i].format;
            tmpChr=charCodes[i].chr
        }
        xssChars.push(tmpFormat.replace('{}','\\u00'+tmpChr));
        xssChars.push(tmpFormat.replace('{}','%'+tmpChr));//1次encode
        xssChars.push(tmpFormat.replace('{}','%25'+tmpChr));//2次encode
        filterChars.push(tmpFormat.replace('{}','&#x'+tmpChr+';'));
        filterChars.push(tmpFormat.replace('{}','%26%23x'+tmpChr+'%3B'));//1次encode
        filterChars.push(tmpFormat.replace('{}','%2526%2523x' + tmpChr + '%253B'));//2次encode
    }
    for(let i=0;i<xssChars.length;i++){
        oriStr=oriStr.replace(new RegExp(xssChars[i],'gi'),filterChars[i]);
    }
    //预防script:
    oriStr=oriStr.replace(/script[\u000d\u000a\u0020]+\:/,'script&#x3a;');
    return oriStr;
}

/**
 * 创建并返回一个像节流阀一样的函数，当重复调用函数的时候，最多每隔 wait毫秒调用一次该函数
 * @param func 执行函数
 * @param wait 时间间隔
 * @param options 如果你想禁用第一次首先执行的话，传递{leading: false}，
 *                如果你想禁用最后一次执行的话，传递{trailing: false}
 * @returns {Function}
 */
function throttle(func, wait, options) {
    let context; let args; let result;
    let timeout = null;
    let previous = 0;
    if (!options) options = {};
    const later = function () {
        previous = options.leading === false ? 0 : new Date().getTime();
        timeout = null;
        result = func.apply(context, args);
        if (!timeout) {
            context = null;
            args = null;
        }
    };
    return function () {
        const now = new Date().getTime();
        if (!previous && options.leading === false) previous = now;
        const remaining = wait - (now - previous);
        context = this;
        args = arguments;
        if (remaining <= 0 || remaining > wait) {
            if (timeout) {
                clearTimeout(timeout);
                timeout = null;
            }
            previous = now;
            result = func.apply(context, args);
            if (!timeout) {
                context = null;
                args = null;
            }
        } else if (!timeout && options.trailing !== false) {
            timeout = setTimeout(later, remaining);
        }
        return result;
    };
}

export default {
    getCookie,
    setCookie,
    clearCookie,
    getUrlParameter,
    updateParameter,
    filterXSS,
    throttle
}
